/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.opengoofy.index12306.biz.orderservice.mq.produce;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.opengoofy.index12306.biz.orderservice.common.constant.OrderRocketMQConstant;
import org.opengoofy.index12306.biz.orderservice.mq.domain.MessageWrapper;
import org.opengoofy.index12306.biz.orderservice.mq.event.DelayCloseOrderEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * 延迟关闭订单生产者
 * 公众号：马丁玩编程，回复：加群，添加马哥微信（备注：12306）获取项目资料
 */
@Slf4j
@Component
public class DelayCloseOrderSendProduce extends AbstractCommonSendProduceTemplate<DelayCloseOrderEvent> {

    private final ConfigurableEnvironment environment;

    public DelayCloseOrderSendProduce(@Autowired RocketMQTemplate rocketMQTemplate, @Autowired ConfigurableEnvironment environment) {
        super(rocketMQTemplate);
        this.environment = environment;
    }

    /**
     * 构建基础发送扩展参数
     * 该方法用于组装延迟关闭订单事件的消息发送扩展参数，主要包括事件名称、关联键、主题、标签、发送超时时间和延迟级别
     * 
     * @param messageSendEvent 消息发送事件，包含订单相关信息
     * @return 返回组装好的BaseSendExtendDTO对象，用于配置消息发送的扩展参数
     */
    @Override
    protected BaseSendExtendDTO buildBaseSendExtendParam(DelayCloseOrderEvent messageSendEvent) {
        return BaseSendExtendDTO.builder()
                .eventName("延迟关闭订单") // 设置事件名称
                .keys(messageSendEvent.getOrderSn()) // 设置消息关联的唯一键值，通常为订单号
                .topic(environment.resolvePlaceholders(OrderRocketMQConstant.ORDER_DELAY_CLOSE_TOPIC_KEY)) // 从配置中解析主题
                .tag(environment.resolvePlaceholders(OrderRocketMQConstant.ORDER_DELAY_CLOSE_TAG_KEY)) // 从配置中解析标签
                .sentTimeout(2000L) // 设置消息发送超时时间为2000毫秒
                // RocketMQ 延迟消息级别 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
                .delayLevel(14) // 设置消息延迟级别为14，即20分钟
                .build(); // 构建并返回BaseSendExtendDTO对象
    }

    /**
     * 用于构建消息的重写方法
     * 主要作用是将业务消息和扩展信息包装成RocketMQ可识别的消息对象
     * 
     * @param messageSendEvent 延迟关闭订单事件，代表了一条需要发送的消息
     * @param requestParam 扩展参数，包含了消息发送的附加信息
     * @return 返回一个Message对象，包含了要发送的消息内容和必要的消息属性
     */
    @Override
    protected Message<?> buildMessage(DelayCloseOrderEvent messageSendEvent, BaseSendExtendDTO requestParam) {
        // 生成或获取消息的唯一键值，用于消息的路由和查找
        String keys = StrUtil.isEmpty(requestParam.getKeys()) ? UUID.randomUUID().toString() : requestParam.getKeys();
        
        // 使用MessageBuilder创建一个消息对象，将业务消息和扩展信息包装起来
        // MessageWrapper进一步封装了原始的业务消息，以便在消息体中传递更多上下文信息
        // 设置消息的键值和标签，用于RocketMQ的消息路由和过滤
        return MessageBuilder
                .withPayload(new MessageWrapper(requestParam.getKeys(), messageSendEvent))
                .setHeader(MessageConst.PROPERTY_KEYS, keys)
                .setHeader(MessageConst.PROPERTY_TAGS, requestParam.getTag())
                .build();
    }
}
